package com.ess.project.examine.record.compute;


import lombok.Getter;
import lombok.Setter;

/**
 * @Description: 基础类
 * @Date: Created in 8:01 上午 2021/3/11
 * @Author: daihui
 * @Modified By:
 */
public interface BaseExamine<T extends Number> {

    String EXAMINATION_ITEM_3000KM = "3000米跑";
    String EXAMINATION_ITEM_PULL_UP = "引体向上";
    String EXAMINATION_ITEM_FLEX_ARM_HANG = "曲臂悬垂";
    String EXAMINATION_ITEM_PUSH_UP = "俯卧撑";
    String EXAMINATION_ITEM_SITUP = "仰卧起坐";
    String EXAMINATION_ITEM_SNAKE_RUN = "蛇形跑";

    Integer MIN_AGE = 1, MAX_AGE = 100, AGE_24 = 24, AGE_25 = 25;
    Integer AGE_27 = 27, AGE_28 = 28, AGE_29 = 29, AGE_30 = 30;
    Integer AGE_31 = 31, AGE_33 = 33, AGE_34 = 34, AGE_36 = 36;
    Integer AGE_37 = 37, AGE_39 = 39, AGE_40 = 40, AGE_42 = 42;
    Integer AGE_43 = 43, AGE_45 = 45, AGE_46 = 46, AGE_48 = 48;
    Integer AGE_49 = 49, AGE_50 = 50, AGE_51 = 51, AGE_52 = 52;
    Integer AGE_54 = 54, AGE_55 = 55, AGE_57 = 57, AGE_58 = 58;
    Integer AGE_59 = 59, AGE_60 = 60;
    /**
     * 各年龄段字典数据key
     */
    Integer DATA_KEY_24 = 24, DATA_KEY_2527 = 2527, DATA_KEY_2830 = 2830, DATA_KEY_3133 = 3133;
    Integer DATA_KEY_3436 = 3436, DATA_KEY_3739 = 3739, DATA_KEY_4042 = 4042, DATA_KEY_4345 = 4345;
    Integer DATA_KEY_4648 = 4648, DATA_KEY_4951 = 4951, DATA_KEY_5254 = 5254, DATA_KEY_5557 = 5557, DATA_KEY_5860 = 5860;
    /**
     * 体型各年龄段字典数据key
     */
    Integer DATA_KEY_2529 = 2529, DATA_KEY_3039 = 3039, DATA_KEY_4049 = 4049, DATA_KEY_5059 = 5059, DATA_KEY_60 = 60;

    Integer MIN_NUMBER = 0;
    Integer MAX_NUMBER = 10000000;
    String MAN = "男";

    String FIRST_KIND = "firstKind";
    String SECOND_KIND = "secondKind";
    String THIRD_KIND = "thirdKind";

    String QUALIFIED_MESSAGE = "合格";
    String UNQUALIFIED_MESSAGE = "不合格";

    String FIRST_KIND_MESSAGE = "一类人员";
    String SECOND_KIND_MESSAGE = "二类人员";
    String THIRD_KIND_MESSAGE = "三类人员";

    Integer FIRST_KIND_PASS_SCORE = 65;
    Integer SECOND_KIND_PASS_SCORE = 60;
    Integer THIRD_KIND_PASS_SCORE = 55;

    /**
     * 计算某项成绩
     *
     * @param args，年龄(Object类是为了计算等级不再自己创建方法单独写)
     * @param gender，性别
     * @param grade     成绩，不定参数
     * @return 数据字典key
     * <p>
     * 该方法体不会抛出ClassCastException异常，通过下面选项来消除警告
     */
    @SuppressWarnings({"unchecked", "varargs"})
    Object compute(Object args, String gender, T... grade);

    /**
     * 根据年龄找到该年龄所在的年龄段，返回该年龄段字典的key
     * @param age 年龄
     * @return 常规体能考核字典key
     */
    static Integer dicKey(Integer age) {
        if (Math.max(MIN_AGE, age) == Math.min(age, AGE_24)) {
            return DATA_KEY_24;
        } else if (Math.max(AGE_25, age) == Math.min(age, AGE_27)) {
            return DATA_KEY_2527;
        } else if (Math.max(AGE_28, age) == Math.min(age, AGE_30)) {
            return DATA_KEY_2830;
        } else if (Math.max(AGE_31, age) == Math.min(age, AGE_33)) {
            return DATA_KEY_3133;
        } else if (Math.max(AGE_34, age) == Math.min(age, AGE_36)) {
            return DATA_KEY_3436;
        } else if (Math.max(AGE_37, age) == Math.min(age, AGE_39)) {
            return DATA_KEY_3739;
        } else if (Math.max(AGE_40, age) == Math.min(age, AGE_42)) {
            return DATA_KEY_4042;
        } else if (Math.max(AGE_43, age) == Math.min(age, AGE_45)) {
            return DATA_KEY_4345;
        } else if (Math.max(AGE_46, age) == Math.min(age, AGE_48)) {
            return DATA_KEY_4648;
        } else if (Math.max(AGE_49, age) == Math.min(age, AGE_51)) {
            return DATA_KEY_4951;
        } else if (Math.max(AGE_52, age) == Math.min(age, AGE_54)) {
            return DATA_KEY_5254;
        } else if (Math.max(AGE_55, age) == Math.min(age, AGE_57)) {
            return DATA_KEY_5557;
        } else if (Math.max(AGE_58, age) == Math.min(age, AGE_60)) {
            return DATA_KEY_5860;
        }
        return -1;
    }

    /**
     * 根据年龄找到该年龄所在的年龄段，返回该年龄段体型字典的key
     * @param age 年龄
     * @return 体型字典key
     */
    static Integer bodyFatDicKey(Integer age) {
        if (Math.max(MIN_AGE, age) == Math.min(age, AGE_24)) {
            return DATA_KEY_24;
        } else if (Math.max(AGE_25, age) == Math.min(age, AGE_29)) {
            return DATA_KEY_2529;
        } else if (Math.max(AGE_30, age) == Math.min(age, AGE_39)) {
            return DATA_KEY_3039;
        } else if (Math.max(AGE_40, age) == Math.min(age, AGE_49)) {
            return DATA_KEY_4049;
        } else if (Math.max(AGE_50, age) == Math.min(age, AGE_59)) {
            return DATA_KEY_5059;
        } else if (Math.max(AGE_60, age) == Math.min(age, MAX_AGE)) {
            return DATA_KEY_60;
        }
        return -1;
    }

    /**
     * 查字典，匹配对应的分数
     *
     * @param second 成绩
     * @param term   项目
     * @param arr    字典数组
     * @return 分数
     */
    static Integer getScore(Integer second, String term, Integer[] arr) {
        int score = 0;
        if (Math.max(arr[0], second) == Math.min(second, arr[1])) {
            score = 55;
        }
        if (Math.max(arr[2], second) == Math.min(second, arr[3])) {
            score = 60;
        }
        if (Math.max(arr[4], second) == Math.min(second, arr[5])) {
            score = 65;
        }
        if (Math.max(arr[6], second) == Math.min(second, arr[7])) {
            score = 70;
        }
        if (Math.max(arr[8], second) == Math.min(second, arr[9])) {
            score = 75;
        }
        if (Math.max(arr[10], second) == Math.min(second, arr[11])) {
            score = 80;
        }
        if (Math.max(arr[12], second) == Math.min(second, arr[13])) {
            score = 85;
        }
        if (Math.max(arr[14], second) == Math.min(second, arr[15])) {
            score = 90;
        }
        if (Math.max(arr[16], second) == Math.min(second, arr[17])) {
            score = 95;
        }
        if (Math.max(arr[18], second) == Math.min(second, arr[19])) {
            score = 100 + extraPoint(term, arr[18], second);
        }
        return score;
    }

    static String qualified(float height, float weight, float bodyFat, Float[] arr) {
        float bmi = weight / (height * height);
        String qualifiedMessage = IsQualifiedEnum.getMessage(false);
        //  BMI值(体型)比较
        if (Math.max(arr[0], bmi) == Math.min(bmi, arr[1])) {
            return IsQualifiedEnum.getMessage(true);
        }
        // 体脂比较
        else if (Math.max(arr[2], bodyFat) == Math.min(bodyFat, arr[3])) {
            return IsQualifiedEnum.getMessage(true);
        }
        return qualifiedMessage;
    }

    /**
     * 等级划分
     *
     * @param totalScore 总分
     * @param arr        某类人员各等级分
     * @return 等级
     */
    static String evaluate(int totalScore, Integer[] arr) {
        String level = "不及格";
        if (Math.max(MIN_NUMBER, totalScore) == Math.min(totalScore, arr[0])) {}
        if (Math.max(arr[0], totalScore) == Math.min(totalScore, arr[1])) {
            level = "及格";
        }
        if (Math.max(arr[1], totalScore) == Math.min(totalScore, arr[2])) {
            level = "良好";
        }
        if (Math.max(arr[2], totalScore) == Math.min(totalScore, arr[3])) {
            level = "优秀";
        }
        if (Math.max(arr[3], totalScore) == Math.min(totalScore, arr[4])) {
            level = "特3级";
        }
        if (Math.max(arr[4], totalScore) == Math.min(totalScore, arr[5])) {
            level = "特2级";
        }
        if (totalScore == arr[5]) {
            level = "特1级";
        }
        return level;
    }

    enum IsQualifiedEnum {
        /* 合格/不合格 */
        QUALIFIED(true, QUALIFIED_MESSAGE),
        UNQUALIFIED(false, UNQUALIFIED_MESSAGE);
        @Getter
        @Setter
        private Boolean qualified;
        @Getter
        @Setter
        private String message;

        IsQualifiedEnum(Boolean qualified, String message) {
            this.qualified = qualified;
            this.message = message;
        }

        public static String getMessage(boolean qualified) {
            IsQualifiedEnum[] typeOfTestEnums = IsQualifiedEnum.values();
            for (IsQualifiedEnum qualifiedEnum : typeOfTestEnums) {
                if (qualifiedEnum.qualified == qualified) {
                    return qualifiedEnum.getMessage();
                }
            }
            return "";
        }
    }

    enum PersonnelKindEnum {
        /**
         * 人员等级和字典key
         */
        FIRST(FIRST_KIND_MESSAGE, FIRST_KIND),
        SECOND(SECOND_KIND_MESSAGE, SECOND_KIND),
        THIRD(THIRD_KIND_MESSAGE, THIRD_KIND);
        @Getter
        @Setter
        private String kind;
        @Getter
        @Setter
        private String key;

        PersonnelKindEnum(String kind, String key) {
            this.kind = kind;
            this.key = key;
        }

        public static String getKey(String kind) {
            PersonnelKindEnum[] personnelKindEnums = PersonnelKindEnum.values();
            for (PersonnelKindEnum personnelKindEnum : personnelKindEnums) {
                if (personnelKindEnum.kind.equals(kind)) {
                    return personnelKindEnum.getKey();
                }
            }
            return "";
        }
    }

    /**
     * 计算附加分
     *
     * @param item      项目
     * @param bestScore 该项目最好成绩
     * @param score     自己的成绩
     * @return 附加分
     */
    static Integer extraPoint(String item, Integer bestScore, Integer score) {
        int extraPoint = 0;
        // 3000米跑，超出100分后每递减5秒增加1分
        if (EXAMINATION_ITEM_3000KM.equals(item)) {
            extraPoint = (score - bestScore) / 5;
        }
        // 引体向上，单杠引体向上超出100分后每递增1次增加1分
        if (EXAMINATION_ITEM_PULL_UP.equals(item)) {
            extraPoint = score - bestScore;
        }
        // 曲臂悬垂，单杠屈臂悬垂超出100分后每递增5秒增加1分
        if (EXAMINATION_ITEM_FLEX_ARM_HANG.equals(item)) {
            extraPoint = (score - bestScore) / 5;
        }
        // 俯卧撑/仰卧起坐，俯卧撑超出100分后每递增2次增加1分
        if (EXAMINATION_ITEM_PUSH_UP.equals(item) || EXAMINATION_ITEM_SITUP.equals(item)) {
            extraPoint = (score - bestScore) / 2;
        }
        // 蛇形跑，超出100分后每递减0.1秒增加1分（1000*0.1）
        if (EXAMINATION_ITEM_SNAKE_RUN.equals(item)) {
            extraPoint = (score - bestScore) / 100;
        }
        return extraPoint;
    }

}
